package com.cnap.config;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.cnap.model.common.CommonResult;
import com.cnap.model.common.ResultCode;
import com.cnap.utils.JsonUtil;
import com.cnap.utils.TokenUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * token校验
 *
 * @author xc
 **/
@WebFilter(urlPatterns = "/api/*")
public class TokenFilter implements Filter {

    private final UserSysConfig userSysConfig;

    @Autowired
    public TokenFilter(UserSysConfig userSysConfig) {
        this.userSysConfig = userSysConfig;
    }

    private static final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class);

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String token = request.getHeader("Authorization");
        // 判断token
        // 如果没有token
        // 或者token校验失败
        // 则返回401
        if (Objects.isNull(token) || !checkToken(token)) {
            LOGGER.error("token is invalid");
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            servletResponse.setContentType("application/json");
            servletResponse.setCharacterEncoding("utf-8");
            servletResponse.getWriter().println(JsonUtil.objectToJsonStr(CommonResult.failed(ResultCode.UNAUTHORIZED)));
            return;
        }
        // 使用ThreadLocal缓存token
        // 只能在同一个线程使用
        // 异步任务需要手动传入token
        TokenUtils.setTOKEN(token);

        filterChain.doFilter(servletRequest, servletResponse);
    }

    private boolean checkToken(String token) {
        try {
            JWT jwt = JWT.of(token);
            int expTime = (int) jwt.getPayload("exp");
            if (expTime < System.currentTimeMillis() / 1000) {
                return false;
            }
            // 需要使用密钥解密
            // 否则，token校验失去意义
            return jwt.setSigner(JWTSignerUtil.hs256(Base64Decoder.decode(userSysConfig.getSecret()))).verify();

        } catch (Exception e) {
            LOGGER.error("parse token error, {}", e.getMessage());
        }
        return false;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
